//
// AWS Manager - A free AWS console application demonstrating advanced concepts
// Copyright (C) 2008-2010 Sean O'Dell. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.awsmanager.common;

import com.sun.data.provider.RowKey;
import com.sun.data.provider.impl.ObjectListDataProvider;
import com.xerox.amazonws.ec2.AttachmentInfo;
import com.xerox.amazonws.ec2.EC2Exception;
import com.xerox.amazonws.ec2.VolumeInfo;
import com.xerox.amazonws.sdb.Domain;
import com.xerox.amazonws.sdb.Item;
import com.xerox.amazonws.sdb.ItemAttribute;
import com.xerox.amazonws.sdb.QueryWithAttributesResult;
import com.xerox.amazonws.sdb.SDBException;
import com.xerox.amazonws.sdb.SimpleDB;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Sean ODell
 */
public class EBSVolumeDataProvider extends ObjectListDataProvider {

    private ArrayList ebsVolumeList = new ArrayList();
    private EC2Connection ec2connection;
    private SimpleDB simpleDB;
    private Domain sdbdomain = null;

    /** Creates a new instance of EBSVolumeDataProvider */
    public EBSVolumeDataProvider() {
        setList(ebsVolumeList);
        setObjectType(EBSVolume.class);
    }

    public void load(EC2Connection ec2connection, SDBConnection sdbconnection) {

        clearObjectList();

        if (ec2connection == null) {
            this.ec2connection = null;
            return;
        } else {
            this.ec2connection = ec2connection;
        }

        if ((this.ec2connection = ec2connection) == null) {
            return;
        }

        List<ItemAttribute> sdbattributes = null;
        String sdbdomainname = null;
        String attributename = null;
        Map sdbSnapshotItems = null;
        Map sdbVolumeItems = null;
        Map sdbInstanceItems = null;

        ArrayList<String> sdbattributesList = new ArrayList<String>();
        sdbattributesList.add("type");
        sdbattributesList.add("name");
        sdbattributesList.add("description");
        sdbattributesList.add("ownernamelast");
        sdbattributesList.add("ownernamefirst");
        sdbattributesList.add("ownerdept");

        ArrayList<String> sdbattributesName = new ArrayList<String>();
        sdbattributesName.add("name");

        sdbdomain = null;

        if ((simpleDB = sdbconnection.getsimpleDB()) != null) {
            sdbdomainname = sdbconnection.getsdbdomain();

            try {
                sdbdomain = simpleDB.getDomain(sdbdomainname);
            } catch (SDBException ex) {
                sdbdomain = null;
                Logger.getLogger(EBSVolumeDataProvider.class.getName()).log(Level.SEVERE, null, ex);
            }

            try {
                sdbdomain.getItem("test").getAttributes();
            } catch (SDBException ex) {
                try {
                    sdbdomain = simpleDB.createDomain(sdbdomainname);
                } catch (SDBException ex1) {
                    Logger.getLogger(EBSVolumeDataProvider.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }

            QueryWithAttributesResult queryResult = null;
            String nextToken = "";

            if (sdbdomain != null) {
                try {
                    queryResult = sdbdomain.selectItems("select * from "
                            + sdbdomainname + " where type = 'volume'", nextToken, true);
                } catch (SDBException ex) {
                    Logger.getLogger(EBSSnapshotDataProvider.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (queryResult != null) {
                    sdbVolumeItems = queryResult.getItems();
                }

                try {
                    queryResult = sdbdomain.selectItems("select * from "
                            + sdbdomainname + " where type = 'instance'", nextToken, true);
                } catch (SDBException ex) {
                    Logger.getLogger(EBSSnapshotDataProvider.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (queryResult != null) {
                    sdbInstanceItems = queryResult.getItems();
                }

                try {
                    queryResult = sdbdomain.selectItems("select * from "
                            + sdbdomainname + " where type = 'snapshot'", nextToken, true);
                } catch (SDBException ex) {
                    Logger.getLogger(EBSSnapshotDataProvider.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (queryResult != null) {
                    sdbSnapshotItems = queryResult.getItems();
                }

            }
        }

        List<String> params = new ArrayList<String>();
        params = new ArrayList<String>();
        List<VolumeInfo> ebsVolumes = null;

        ArrayList<String> ec2Regions = ec2connection.getEc2RegionNames();
        EC2Region ec2RegionInfo = null;

        for (String ec2Region : ec2Regions) {

            ec2RegionInfo = (EC2Region) ec2connection.getEc2RegionInfo().get(ec2Region);

            try {
                ebsVolumes = ec2RegionInfo.getRegionConnection().describeVolumes(params);
            } catch (EC2Exception ex) {
                Logger.getLogger(EBSVolumeDataProvider.class.getName()).log(Level.SEVERE, null, ex);
            }

            for (VolumeInfo vol : ebsVolumes) {

                EBSVolume ebsVolume = new EBSVolume();

                ebsVolume.setVolumeRegion(ec2Region);
                ebsVolume.setvolumeId(vol.getVolumeId());
                ebsVolume.setsize(vol.getSize());
                ebsVolume.setsnapshotId(vol.getSnapshotId());
                ebsVolume.setzone(vol.getZone());
                ebsVolume.setvstatus(vol.getStatus());
                ebsVolume.setcreateTime(vol.getCreateTime());

                List<AttachmentInfo> ebsAttachments = vol.getAttachmentInfo();

                if (ebsAttachments.size() != 0) {
                    for (AttachmentInfo attachment : ebsAttachments) {
                        ebsVolume.setinstanceId(attachment.getInstanceId());
                        ebsVolume.setdevice(attachment.getDevice());
                        ebsVolume.setastatus(attachment.getStatus());
                        ebsVolume.setattachTime(attachment.getAttachTime());
                    }
                } else {
                    ebsVolume.setinstanceId("NA");
                    ebsVolume.setdevice("NA");
                    ebsVolume.setattachTime("NA");
                    ebsVolume.setastatus("NA");
                }

                if (sdbdomain != null) {
                    sdbattributes = (List<ItemAttribute>) sdbVolumeItems.get(vol.getVolumeId());
                    if (sdbattributes != null) {
                        if (sdbattributes.size() > 0) {
                            for (ItemAttribute attribute : sdbattributes) {
                                attributename = attribute.getName();
                                if (attributename.equals("name")) {
                                    ebsVolume.setvolname(attribute.getValue());
                                } else if (attributename.equals("description")) {
                                    ebsVolume.setvoldesc(attribute.getValue());
                                } else if (attributename.equals("ownernamelast")) {
                                    ebsVolume.setvolownernamelast(attribute.getValue());
                                } else if (attributename.equals("ownernamefirst")) {
                                    ebsVolume.setvolownernamefirst(attribute.getValue());
                                } else if (attributename.equals("ownerdept")) {
                                    ebsVolume.setvolownerdept(attribute.getValue());
                                }
                            }
                        }
                    }
                }

                // get the name of the instance for which the volume is attached.
                if (ebsVolume.getinstanceId() != null) {
                    if (!ebsVolume.getinstanceId().equals("")
                            && sdbdomain != null) {
                        sdbattributes = (List<ItemAttribute>) sdbInstanceItems.get(ebsVolume.getinstanceId());
                        if (sdbattributes != null) {
                            if (sdbattributes.size() > 0) {
                                for (ItemAttribute attribute : sdbattributes) {
                                    attributename = attribute.getName();
                                    if (attributename.equals("name")) {
                                        ebsVolume.setInstname(attribute.getValue());
                                    }
                                }
                            }
                        }
                    }
                }

                // get the name of the snapshot from which the volume was created.
                if (ebsVolume.getsnapshotId() != null) {
                    if (!ebsVolume.getsnapshotId().equals("")
                            && sdbdomain != null) {
                        sdbattributes = (List<ItemAttribute>) sdbSnapshotItems.get(ebsVolume.getsnapshotId());
                        if (sdbattributes != null) {
                            if (sdbattributes.size() > 0) {
                                for (ItemAttribute attribute : sdbattributes) {
                                    attributename = attribute.getName();
                                    if (attributename.equals("name")) {
                                        ebsVolume.setSnapname(attribute.getValue());
                                    }
                                }
                            }
                        }
                    }
                }
                getList().add(ebsVolume);
            }
        }
    }

    public EBSVolume getVolume(RowKey rowKey) {
        EBSVolume ebsVolume = (EBSVolume) getObject(rowKey);
        return ebsVolume;
    }

    public EBSVolume getVolume(String id) {
        for (int i = 0; i < ebsVolumeList.size(); i++) {
            EBSVolume ebsVolume = (EBSVolume) ebsVolumeList.get(i);
            if (ebsVolume.getvolumeId().equals(id)) {
                return ebsVolume;
            }
        }
        return null;
    }

    public int getVolumeIndex(String id) {
        for (int i = 0; i < ebsVolumeList.size(); i++) {
            EBSVolume ebsVolume = (EBSVolume) ebsVolumeList.get(i);
            if (ebsVolume.getvolumeId().equals(id)) {
                return i;
            }
        }
        return -1;
    }

    public String createVolume(Map volInfo) {

        int v = 0;
        String statusMsg = new String();

        if (this.ec2connection == null) {
            return "Connection to AWS timed out.";
        } else {
            if (this.ec2connection.getEc2RegionInfo() == null) {
                return "Connection to AWs timed out.";
            }
        }

        Integer volCount = (Integer) volInfo.get("volcount");
        Integer volSize = (Integer) volInfo.get("volsize");
        String snapID = (String) volInfo.get("snapID");
        String zone = (String) volInfo.get("zone");

        Map ec2Zones = ec2connection.getEc2ZoneToRegion();

        EC2Region ec2RegionInfo = null;
        ec2RegionInfo = (EC2Region) ec2connection.getEc2RegionInfo().get(ec2Zones.get(zone));

        for (v = 1; v <= volCount; v++) {
            statusMsg = statusMsg + "\nStatus for volume " + v + ":\n";
            try {
                VolumeInfo volumeInfo = ec2RegionInfo.getRegionConnection().createVolume(volSize.toString(), snapID, zone);
                if (volumeInfo != null) {
                    statusMsg = statusMsg + "  Volume ID        : " + volumeInfo.getVolumeId() + "\n";
                    statusMsg = statusMsg + "  Volume status    : " + volumeInfo.getStatus() + "\n";
                    statusMsg = statusMsg + "  Availability zone: " + volumeInfo.getZone() + "\n";
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage() != null) {
                    statusMsg = statusMsg + "  Error: " + e.getMessage() + "\n";
                }
            }
        }
        return statusMsg;
    }

    public String attachVolumes(Map attachVolInfo) {

        String statusMsg = new String();

        String instanceID = (String) attachVolInfo.get("instanceID");
        ArrayList deviceIDsList = (ArrayList) attachVolInfo.get("deviceList");
        ArrayList attachVolsList = (ArrayList) attachVolInfo.get("rowKeys");

        for (int i = 0; i < attachVolsList.size(); i++) {

            EBSVolume ebsVolume = getVolume((RowKey) attachVolsList.get(i));
            String deviceID = (String) deviceIDsList.get(i);
            String volumeID = ebsVolume.getvolumeId();
            String region = ebsVolume.getVolumeRegion();
            EC2Region ec2RegionInfo = (EC2Region) ec2connection.getEc2RegionInfo().get(region);

            statusMsg = statusMsg + "\nStatus for volume " + ebsVolume.getvolumeId().toString() + ":\n";

            try {
                AttachmentInfo attachmentInfo = ec2RegionInfo.getRegionConnection().attachVolume(volumeID, instanceID, deviceID);
                if (attachmentInfo != null) {
                    statusMsg = statusMsg + "  Instance ID: " + attachmentInfo.getInstanceId() + "\n";
                    statusMsg = statusMsg + "  Device ID  : " + attachmentInfo.getDevice() + "\n";
                    statusMsg = statusMsg + "  Status     : " + attachmentInfo.getStatus() + "\n";
                }

            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage() != null) {
                    statusMsg = statusMsg + "  Error: " + e.getMessage() + "\n";
                }
            }
        }
        return statusMsg;

    }

    public String detachVolume(Map detachVolInfo) {

        ArrayList detachVolsList = (ArrayList) detachVolInfo.get("rowKeys");
        String statusMsg = new String();

        for (int i = 0; i < detachVolsList.size(); i++) {

            EBSVolume ebsVolume = getVolume((RowKey) detachVolsList.get(i));
            String volID = ebsVolume.getvolumeId();
            String instID = ebsVolume.getinstanceId();
            String deviceID = ebsVolume.getdevice();
            String region = ebsVolume.getVolumeRegion();
            EC2Region ec2RegionInfo = (EC2Region) ec2connection.getEc2RegionInfo().get(region);

            statusMsg = statusMsg + "\nStatus for volume " + ebsVolume.getvolumeId() + ":\n";

            AttachmentInfo attachmentInfo = null;
            try {
                attachmentInfo = ec2RegionInfo.getRegionConnection().detachVolume(volID, instID, deviceID, false);
            } catch (EC2Exception ex) {
                Logger.getLogger(EBSVolumeDataProvider.class.getName()).log(Level.SEVERE, null, ex);
                if (ex.getMessage() != null) {
                    statusMsg = statusMsg + "  Error: " + ex.getMessage() + "\n";
                }

            }
            if (attachmentInfo != null) {
                statusMsg = statusMsg + "  Instance ID: " + attachmentInfo.getInstanceId() + "\n";
                statusMsg = statusMsg + "  Device ID  : " + attachmentInfo.getDevice() + "\n";
                statusMsg = statusMsg + "  Status     : " + attachmentInfo.getStatus() + "\n";
            }
        }
        return statusMsg;
    }

    public String deleteVolume(List<RowKey> rowKeys) {

        String statusMsg = new String();

        for (RowKey rowKey : rowKeys) {
            EBSVolume ebsVolume = this.getVolume(rowKey);
            String volid = ebsVolume.getvolumeId();
            String region = ebsVolume.getVolumeRegion();
            EC2Region ec2RegionInfo = (EC2Region) ec2connection.getEc2RegionInfo().get(region);
            try {
                ec2RegionInfo.getRegionConnection().deleteVolume(volid);
                statusMsg = statusMsg + "Deleteing volume: " + region + ", " + volid + "\n";
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage() != null) {
                    statusMsg = statusMsg + "Error: " + e.getMessage() + "\n";
                }
            }
        }
        return statusMsg;
    }

    public String updateVolume(Map volinfo) {

        int volIndex = -1;
        String statusMsg = new String();
        Item sdbitem = null;
        List<ItemAttribute> sdbattributes = new ArrayList<ItemAttribute>();

        String volid = (String) volinfo.get("volid");

        if (sdbdomain != null) {
            try {
                sdbitem = sdbdomain.getItem(volid);

                sdbattributes.add(new ItemAttribute("type", (String) volinfo.get("type"), true));
                sdbattributes.add(new ItemAttribute("name", (String) volinfo.get("volname"), true));
                sdbattributes.add(new ItemAttribute("size", (String) volinfo.get("volsize"), true));
                sdbattributes.add(new ItemAttribute("createtime", (String) volinfo.get("volcreatetime"), true));
                sdbattributes.add(new ItemAttribute("description", (String) volinfo.get("voldesc"), true));
                sdbattributes.add(new ItemAttribute("ownernamelast", (String) volinfo.get("volownernamelast"), true));
                sdbattributes.add(new ItemAttribute("ownernamefirst", (String) volinfo.get("volownernamefirst"), true));
                sdbattributes.add(new ItemAttribute("ownerdept", (String) volinfo.get("volownerdept"), true));

                sdbitem.putAttributes(sdbattributes);

                EBSVolume ebsVolume = getVolume(volid);
                volIndex = getVolumeIndex(volid);

                ebsVolume.setvolname((String) volinfo.get("volname"));
                ebsVolume.setvoldesc((String) volinfo.get("voldesc"));
                ebsVolume.setvolownernamelast((String) volinfo.get("volownernamelast"));
                ebsVolume.setvolownernamefirst((String) volinfo.get("volownernamefirst"));
                ebsVolume.setvolownerdept((String) volinfo.get("volownerdept"));

                ebsVolumeList.set(volIndex, ebsVolume);

            } catch (SDBException ex) {
                Logger.getLogger(EBSVolumeDataProvider.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return statusMsg;
    }

    public Map getVolInfoforInstance(String instanceID) {

        Map volInfoforInstance = new HashMap();
        ArrayList deviceList = new ArrayList();

        for (int v = 0; v < ebsVolumeList.size(); v++) {
            EBSVolume ebsVolume = (EBSVolume) ebsVolumeList.get(v);
            String volInstanceID = ebsVolume.getinstanceId();
            if (volInstanceID != null) {
                if (volInstanceID.equals(instanceID)) {
                    deviceList.add(ebsVolume.getdevice());
                }
            }
        }
        Collections.sort(deviceList);
        volInfoforInstance.put("usedDeviceList", deviceList);
        return volInfoforInstance;
    }
}
